package com.controller.lib.upgrade

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller.Session
import android.content.pm.PackageInstaller.SessionParams
import android.net.Uri
import android.os.Environment
import android.text.TextUtils
import com.controller.lib.BootRequestService
import com.controller.lib.utils.FileUtils.Companion.isFileExists
import timber.log.Timber
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.security.MessageDigest

/**
 * @author Administrator
 */
object InstallHelper {
  private const val DOWNLOAD_DIR = "apps"

  val downloadDir: File
    /**
     * 下载应用存储路径
     */
    get() = File(
      Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
      DOWNLOAD_DIR
    )

  /**
   * 替换空格
   */
  fun replaceTrim(text: String): String? {
    if (!TextUtils.isEmpty(text)) {
      return text.trim { it <= ' ' }
    }
    return text
  }

  /**
   * 安装apk
   */
  fun installApkPackage(context: Context, filePath: String?) {
    if (!isFileExists(filePath)) {
      Timber.d("installApkPackage file not exists: %s", filePath)
      return
    }
    var session: Session? = null
    try {
      val packageInstaller = context.packageManager.packageInstaller
      val params =
        SessionParams(SessionParams.MODE_FULL_INSTALL)
      val sessionId = packageInstaller.createSession(params)
      Timber.i("installApk_%s", sessionId)
      session = packageInstaller.openSession(sessionId)
      addApkToInstallSession(filePath, session)
      val intent = Intent(context, ApkInstallReceive::class.java)
      intent.setAction(ApkInstallReceive.PACKAGE_INSTALLED_ACTION)
      intent.setPackage(context.packageName)
      intent.setData(Uri.parse(filePath))
      val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_MUTABLE)
      session.commit(pendingIntent.intentSender)
    } catch (e: IOException) {
      Timber.i("installApk IOException")
      e.printStackTrace()
    } catch (e: RuntimeException) {
      Timber.i("installApk RuntimeException")
      session?.abandon()
      e.printStackTrace()
    }
    Timber.i("install Apk finish")
  }

  fun addApkToInstallSession(filePath: String?, session: Session) {
    try {
      val packageInSession = session.openWrite("package", 0, -1)
      val input = FileInputStream(filePath)
      if (input != null) {
        Timber.i("input.available:_%s ", input.available())
        val buffer = ByteArray(16384)
        var n: Int
        while ((input.read(buffer).also { n = it }) >= 0) {
          packageInSession.write(buffer, 0, n)
        }
      } else {
        Timber.i("addApkToInstallSession failed")
      }
      packageInSession.close() //need to close this stream
      input.close() //need to close this stream
    } catch (e: Exception) {
      Timber.e("addApkToInstallSession failed2 _%s", e)
    }
  }

  /**
   * 重启应用
   *
   * @param delayTime 重启等待时间
   */
  fun restartApp(context: Context, delayTime: Long) {
    try {
//      val intent = context.packageManager
//        .getLaunchIntentForPackage(context.packageName)
//      val restartIntent =
//        PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_MUTABLE)
//      val mgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
//      mgr[AlarmManager.RTC, System.currentTimeMillis() + delayTime] = restartIntent
//      System.exit(0)
//      //android.os.Process.killProcess(android.os.Process.myPid());
      val alarmManager=context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
      val intent:Intent=Intent(context,BootRequestService::class.java)
      intent.action = "android.intent.action.BootRequestService"
      val pendingIntent =
        PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_MUTABLE)
      val triggerTime =  System.currentTimeMillis() + delayTime
      alarmManager[AlarmManager.RTC_WAKEUP, triggerTime] = pendingIntent
      android.os.Process.killProcess(android.os.Process.myPid())
    } catch (e: Exception) {
      throw RuntimeException(e)
    }
  }
}
